package main

import (
    "fmt"
    "time"
)

// Product - 订单产品
type Order struct {
    ID              string
    CustomerID      string
    Items           []OrderItem
    ShippingAddress Address
    BillingAddress  Address
    PaymentMethod   PaymentInfo
    ShippingMethod  ShippingInfo
    Discounts       []Discount
    TotalAmount     float64
    Status          string
    CreatedAt       time.Time
    Notes           string
}

type OrderItem struct {
    ProductID string
    Name      string
    Quantity  int
    Price     float64
    Discount  float64
}

type Address struct {
    Street  string
    City    string
    State   string
    ZipCode string
    Country string
}

type PaymentInfo struct {
    Method     string
    CardNumber string
    ExpiryDate string
    CVV        string
}

type ShippingInfo struct {
    Method            string
    Carrier           string
    TrackingID        string
    EstimatedDelivery time.Time
}

type Discount struct {
    Type        string
    Description string
    Amount      float64
    Percentage  float64
}

func (o *Order) Display() {
    fmt.Printf("订单详情:\n")
    fmt.Printf("  订单ID: %s\n", o.ID)
    fmt.Printf("  客户ID: %s\n", o.CustomerID)
    fmt.Printf("  商品数量: %d\n", len(o.Items))
    fmt.Printf("  总金额: $%.2f\n", o.TotalAmount)
    fmt.Printf("  状态: %s\n", o.Status)
    fmt.Printf("  创建时间: %s\n", o.CreatedAt.Format("2006-01-02 15:04:05"))
    fmt.Printf("  配送地址: %s, %s, %s\n", o.ShippingAddress.City, o.ShippingAddress.State, o.ShippingAddress.Country)
    fmt.Printf("  支付方式: %s\n", o.PaymentMethod.Method)
    fmt.Printf("  配送方式: %s\n", o.ShippingMethod.Method)
    if o.Notes != "" {
        fmt.Printf("  备注: %s\n", o.Notes)
    }
}

// Abstract Builder - 抽象建造者
type OrderBuilder interface {
    SetBasicInfo(orderID, customerID string) OrderBuilder
    AddItem(productID, name string, quantity int, price float64) OrderBuilder
    SetShippingAddress(address Address) OrderBuilder
    SetBillingAddress(address Address) OrderBuilder
    SetPaymentMethod(payment PaymentInfo) OrderBuilder
    SetShippingMethod(shipping ShippingInfo) OrderBuilder
    AddDiscount(discount Discount) OrderBuilder
    SetNotes(notes string) OrderBuilder
    Build() *Order
}

// Concrete Builder - 具体建造者
type ConcreteOrderBuilder struct {
    order *Order
}

func NewOrderBuilder() *ConcreteOrderBuilder {
    return &ConcreteOrderBuilder{
        order: &Order{
            Items:     make([]OrderItem, 0),
            Discounts: make([]Discount, 0),
            Status:    "pending",
            CreatedAt: time.Now(),
        },
    }
}

func (b *ConcreteOrderBuilder) SetBasicInfo(orderID, customerID string) OrderBuilder {
    b.order.ID = orderID
    b.order.CustomerID = customerID
    return b
}

func (b *ConcreteOrderBuilder) AddItem(productID, name string, quantity int, price float64) OrderBuilder {
    item := OrderItem{
        ProductID: productID,
        Name:      name,
        Quantity:  quantity,
        Price:     price,
        Discount:  0,
    }
    b.order.Items = append(b.order.Items, item)
    return b
}

func (b *ConcreteOrderBuilder) SetShippingAddress(address Address) OrderBuilder {
    b.order.ShippingAddress = address
    return b
}

func (b *ConcreteOrderBuilder) SetBillingAddress(address Address) OrderBuilder {
    b.order.BillingAddress = address
    return b
}

func (b *ConcreteOrderBuilder) SetPaymentMethod(payment PaymentInfo) OrderBuilder {
    b.order.PaymentMethod = payment
    return b
}

func (b *ConcreteOrderBuilder) SetShippingMethod(shipping ShippingInfo) OrderBuilder {
    b.order.ShippingMethod = shipping
    return b
}

func (b *ConcreteOrderBuilder) AddDiscount(discount Discount) OrderBuilder {
    b.order.Discounts = append(b.order.Discounts, discount)
    return b
}

func (b *ConcreteOrderBuilder) SetNotes(notes string) OrderBuilder {
    b.order.Notes = notes
    return b
}

func (b *ConcreteOrderBuilder) Build() *Order {
    // 计算总金额
    total := 0.0
    for _, item := range b.order.Items {
        itemTotal := float64(item.Quantity) * item.Price
        itemTotal -= item.Discount
        total += itemTotal
    }
    
    // 应用折扣
    for _, discount := range b.order.Discounts {
        if discount.Type == "fixed" {
            total -= discount.Amount
        } else if discount.Type == "percentage" {
            total -= total * (discount.Percentage / 100)
        }
    }
    
    b.order.TotalAmount = total
    return b.order
}

// Director - 指挥者
type OrderDirector struct {
    builder OrderBuilder
}

func NewOrderDirector(builder OrderBuilder) *OrderDirector {
    return &OrderDirector{builder: builder}
}

func (d *OrderDirector) ConstructSimpleOrder(orderID, customerID string) *Order {
    return d.builder.
        SetBasicInfo(orderID, customerID).
        AddItem("PROD001", "笔记本电脑", 1, 999.99).
        SetShippingAddress(Address{
            Street:  "123 Main St",
            City:    "北京",
            State:   "北京",
            ZipCode: "100000",
            Country: "中国",
        }).
        SetPaymentMethod(PaymentInfo{
            Method:     "信用卡",
            CardNumber: "****1234",
        }).
        SetShippingMethod(ShippingInfo{
            Method:  "标准配送",
            Carrier: "顺丰快递",
        }).
        Build()
}

func (d *OrderDirector) ConstructVIPOrder(orderID, customerID string) *Order {
    return d.builder.
        SetBasicInfo(orderID, customerID).
        AddItem("PROD001", "高端笔记本电脑", 1, 1999.99).
        AddItem("PROD002", "无线鼠标", 1, 99.99).
        AddItem("PROD003", "机械键盘", 1, 299.99).
        SetShippingAddress(Address{
            Street:  "456 VIP Ave",
            City:    "上海",
            State:   "上海",
            ZipCode: "200000",
            Country: "中国",
        }).
        SetBillingAddress(Address{
            Street:  "456 VIP Ave",
            City:    "上海",
            State:   "上海",
            ZipCode: "200000",
            Country: "中国",
        }).
        SetPaymentMethod(PaymentInfo{
            Method:     "VIP信用卡",
            CardNumber: "****5678",
        }).
        SetShippingMethod(ShippingInfo{
            Method:            "VIP快递",
            Carrier:           "顺丰VIP",
            EstimatedDelivery: time.Now().Add(24 * time.Hour),
        }).
        AddDiscount(Discount{
            Type:        "percentage",
            Description: "VIP会员折扣",
            Percentage:  15,
        }).
        SetNotes("VIP客户，优先处理").
        Build()
}

// 使用演示
func main() {
    fmt.Println("=== 订单建造者演示 ===")
    
    // 简单订单
    orderBuilder := NewOrderBuilder()
    orderDirector := NewOrderDirector(orderBuilder)
    
    simpleOrder := orderDirector.ConstructSimpleOrder("ORD001", "CUST123")
    fmt.Println("=== 简单订单 ===")
    simpleOrder.Display()
    fmt.Println()
    
    // VIP订单
    orderBuilder = NewOrderBuilder()
    orderDirector = NewOrderDirector(orderBuilder)
    vipOrder := orderDirector.ConstructVIPOrder("VIP001", "VIP456")
    fmt.Println("=== VIP订单 ===")
    vipOrder.Display()
    fmt.Println()
    
    // 自定义订单
    orderBuilder = NewOrderBuilder()
    customOrder := orderBuilder.
        SetBasicInfo("CUSTOM001", "CUST789").
        AddItem("PROD001", "游戏机", 1, 399.99).
        AddItem("PROD002", "游戏光盘", 3, 59.99).
        SetShippingAddress(Address{
            Street:  "789 Game St",
            City:    "深圳",
            State:   "广东",
            ZipCode: "518000",
            Country: "中国",
        }).
        SetPaymentMethod(PaymentInfo{
            Method:     "支付宝",
            CardNumber: "alipay@example.com",
        }).
        SetShippingMethod(ShippingInfo{
            Method:  "快递",
            Carrier: "中通快递",
        }).
        AddDiscount(Discount{
            Type:        "fixed",
            Description: "新用户优惠",
            Amount:      20.0,
        }).
        SetNotes("请小心包装").
        Build()
    
    fmt.Println("=== 自定义订单 ===")
    customOrder.Display()
}